package org.bulu.project.system.service.impl;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.bulu.project.system.mapper.UserVideoMapper;
import org.bulu.project.system.mapper.VideoStatsMapper;
import org.bulu.project.system.model.entity.UserVideo;
import org.bulu.project.system.model.entity.VideoStats;
import org.bulu.project.system.service.UserVideoService;
import org.bulu.project.system.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.TimeUnit.DAYS;

@Service
@RequiredArgsConstructor
@Slf4j
@Transactional
public class UserVideoServiceImpl implements UserVideoService {

    private final UserVideoMapper userVideoMapper;
    private final VideoStatsMapper VideoStatsMapper;
    private final RedisTemplate<String, Object> redisTemplate;
    @Autowired
    RedisUtil redisUtil;
    @Autowired
    @Qualifier("taskExecutor")
    private Executor taskExecutor;


    @Override
    public List<UserVideo> getVidList(Integer uid, Integer love) {
        return userVideoMapper.getVidList(uid, love);
    }

    @Override
    public List<Integer> getList(Integer uid) {
        return userVideoMapper.getList(uid, 1);
    }

    /* 点赞或点踩，返回更新后的信息
     * @param uid   用户ID
     * @param vid   视频ID
     * @param isLove    赞还是踩 true赞 false踩
     * @param isSet     设置还是取消  true设置 false取消
     * @return  更新后的信息
     */
    @Override
    public UserVideo setLoveOrUnlove(Integer uid, Integer vid, boolean isLove, boolean isSet) {
        // 定义 Redis 的键
        String userKey = "user:" + uid;
        String videoKey = "video:" + vid;
        String loveKey = videoKey + ":love";
        String hateKey = videoKey + ":hate";

        // 更新视频级别的点赞和点踩计数
        String loveCountKey = videoKey + ":love_count";
        String hateCountKey = videoKey + ":hate_count";

        // 检查用户是否已经点赞或点踩
        Boolean hasLove = redisTemplate.opsForHash().hasKey(loveKey, userKey);
        Boolean hasHate = redisTemplate.opsForHash().hasKey(hateKey, userKey);

        // 如果用户要点赞
        if (isLove) {
            // 如果用户已经点赞，取消点赞
            if (hasLove && isSet) {
                redisTemplate.opsForHash().delete(loveKey, userKey);
                redisTemplate.opsForValue().increment(loveCountKey, -1L);
            } else if (!hasLove && isSet) {
                // 如果用户没有点赞并且现在是要点赞，则添加记录并增加计数
                redisTemplate.opsForHash().put(loveKey, userKey, uid);
                redisTemplate.opsForValue().increment(loveCountKey, 1L);

                // 如果之前有点踩，则取消点踩
                if (hasHate) {
                    redisTemplate.opsForHash().delete(hateKey, userKey);
                    redisTemplate.opsForValue().increment(hateCountKey, -1L);
                }
            }
        } else { // 如果用户要点踩
            // 如果用户已经点踩，取消点踩
            if (hasHate && isSet) {
                redisTemplate.opsForHash().delete(hateKey, userKey);
                redisTemplate.opsForValue().increment(hateCountKey, -1L);
            } else if (!hasHate && isSet) {
                // 如果用户没有点踩并且现在是要点踩，则添加记录并增加计数
                redisTemplate.opsForHash().put(hateKey, userKey, uid);
                redisTemplate.opsForValue().increment(hateCountKey, 1L);

                // 如果之前有点赞，则取消点赞
                if (hasLove) {
                    redisTemplate.opsForHash().delete(loveKey, userKey);
                    redisTemplate.opsForValue().increment(loveCountKey, -1L);
                }
            }
        }

        // 获取最新的计数
        Integer loveCount = (Integer) redisTemplate.opsForValue().get(loveCountKey);
        Integer hateCount = (Integer) redisTemplate.opsForValue().get(hateCountKey);

        //更新redis中redis缓存中的点赞量
        VideoStats videoStats = (VideoStats) redisUtil.getValue("videoStats:" + vid);
        if (videoStats == null) {
            // 如果 videoStats 为 null，则创建一个新的 VideoStats 对象
            videoStats = new VideoStats();
            videoStats.setVid(vid);
            videoStats.setCollect(0);
            videoStats.setGood(0); // 显式初始化 good
            videoStats.setBad(0); // 设置 vid
        }

        //从 Redis 删除旧的 videoStats
        redisUtil.delValue("videoStats:" + vid);
        videoStats.setGood(loveCount);
        videoStats.setBad(hateCount);
        VideoStats finalVideoStats = videoStats;
        VideoStatsMapper.update(videoStats);
        CompletableFuture.runAsync(() -> redisUtil.setExValue("videoStats:" + finalVideoStats.getVid(), finalVideoStats,30, DAYS), taskExecutor);


        userVideoMapper.setLoveOrUnlove(uid, vid, isLove, isSet);
        // 更新 MySQL 中的记录
        UserVideo userVideo = userVideoMapper.getUserVideoByUidAndVid(uid, vid);


        // 返回更新后的 UserVideo 实体
        return userVideo;
    }



    /**
     * 收藏或取消收藏
     *
     * @param uid       用户ID
     * @param vid       视频ID
     * @param isCollect 是否收藏 true收藏 false取消
     */


        // ... 其他方法 ...

        /**
         * 收藏或取消收藏
         *
         * @param uid       用户ID
         * @param vid       视频ID
         * @param isCollect 是否收藏 true收藏 false取消
         */
        @Override
        public void collectOrCancel(Integer uid, Integer vid, boolean isCollect) {
            // 定义 Redis 的键
            String userKey = "user:" + uid;
            String videoKey = "video:" + vid;
            String collectKey = videoKey + ":collect";
            String collectCountKey = videoKey + ":collect_count";

            // 检查用户是否已经收藏
            Boolean hasCollected = redisTemplate.opsForHash().hasKey(collectKey, userKey);

            // 更新视频级别的收藏计数
            Integer currentCount = (Integer) redisTemplate.opsForValue().get(collectCountKey);
            if (currentCount == null) {
                redisTemplate.opsForValue().set(collectCountKey, 0L);
                currentCount = 0;
            }



            // 根据 isCollect 的值来更新 Redis
            if (isCollect) {
                // 用户要收藏
                if (!hasCollected) {
                    // 如果用户没有收藏过，则添加记录并增加计数
                    redisTemplate.opsForHash().put(collectKey, userKey, uid);
                    redisTemplate.opsForValue().increment(collectCountKey, 1L);
                } else {
                    // 如果用户已经收藏过，则删除记录并减少计数
                    redisTemplate.opsForHash().delete(collectKey, userKey);
                    redisTemplate.opsForValue().increment(collectCountKey, -1L);
                }
            } else {
                // 用户要取消收藏
                if (hasCollected) {
                    // 如果用户已经收藏过，则删除记录并减少计数
                    redisTemplate.opsForHash().delete(collectKey, userKey);
                    redisTemplate.opsForValue().increment(collectCountKey, -1L);
                } else {
                    // 如果用户已经取消收藏，则重新收藏
                    redisTemplate.opsForHash().put(collectKey, userKey, uid);
                    redisTemplate.opsForValue().increment(collectCountKey, 1L);
                }
            }

            Integer collectCount = (Integer) redisTemplate.opsForValue().get(collectCountKey);
            // 更新 Redis 中的 `VideoStats` 对象
            VideoStats videoStats = (VideoStats) redisUtil.getValue("videoStats:" + vid);
            if (videoStats == null) {
                // 如果 videoStats 为 null，则创建一个新的 VideoStats 对象
                videoStats = new VideoStats();
                videoStats.setVid(vid);// 设置 vid
                videoStats.setGood(0); // 显式初始化 good
                videoStats.setBad(0);
            }

            // 从 Redis 删除旧的 videoStats
            redisUtil.delValue("videoStats:" + vid);
            videoStats.setCollect(collectCount);
            VideoStatsMapper.update(videoStats);

            // 异步更新 Redis 缓存
            VideoStats finalVideoStats = videoStats;
            CompletableFuture.runAsync(() -> redisUtil.setExValue("videoStats:" + finalVideoStats.getVid(), finalVideoStats, 30, TimeUnit.DAYS), taskExecutor);

           /* //更新redis中redis缓存中的点赞量
            VideoStats videoStats = (VideoStats) redisUtil.getValue("videoStats:" + vid);
            redisUtil.delValue("videoStats:" + vid);
            videoStats.setCollect(currentCount);
            VideoStatsMapper.update(videoStats);
            CompletableFuture.runAsync(() -> redisUtil.setExValue("videoStats:" + videoStats.getVid(), videoStats,30, DAYS), taskExecutor);*/



            // 更新 MySQL 中的收藏状态
            // 无论 isCollect 是 true 还是 false，只要用户已经收藏过，则取消收藏
            userVideoMapper.collectOrCancel(uid, vid, hasCollected ? false : isCollect);
        }

    @Override
    public UserVideo getUserVideoInfo(Integer uid, Integer vid) {
        try{
            return userVideoMapper.getUserVideoByUidAndVid(uid, vid);
        }catch (Exception e){
            throw new RuntimeException("获取用户视频信息失败");
        }
    }
}












